package com.heima.nio.socket.server;

import com.heima.nio.bytebuffer.ByteBufferUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * Selector 服务端
 * @author ZhengDp
 * @Date 2023/6/23 14:35
 */
@Slf4j
public class SelectServer {
    public static void main(String[] args) throws IOException {
        // selector 可以管理 多个 Channel
        // 每个 Channel 对应 一个 Socket连接
        // 1. 创建Selector
        Selector selector = Selector.open();
        // 2. 创建 Channel
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.bind(new InetSocketAddress(7777));
        ssc.configureBlocking(false);
        // 3. Channel 注册到 selector
        SelectionKey sscKey = ssc.register(selector, SelectionKey.OP_ACCEPT);

        while(true) {
            selector.select();
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while(iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
                // 判断事件类型，根据不同的事件类型，进行不同的逻辑处理
                if(key.isAcceptable()) {
                    ServerSocketChannel server = (ServerSocketChannel) key.channel();
                    SocketChannel socket = server.accept();
                    // 将 socket 注册到 selector中
                    socket.configureBlocking(false);
                    socket.register(selector,SelectionKey.OP_READ);
                } else if(key.isReadable()) {
                    // 读取数据
                    try {
                        SocketChannel client = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024);

                        int num = client.read(buffer);
                        if(num == -1) {
                            log.warn("客户端断开连接，取消监听事件");
                            key.cancel();
                        } else {
                            // 输出内容
                            buffer.flip();
                            ByteBufferUtil.debugRead(buffer);
                        }
                    }catch (Exception e) {
                        log.error("客户端强制断开连接,取消监听当前事件",e);
                        key.cancel();
                    }
                }
            }
        }


    }
}
